package com.lamda.zhekou.controller;

import com.alibaba.fastjson.JSONObject;
import com.lamda.zhekou.constraints.Configuration;
import com.lamda.zhekou.manager.ServerHostManager;
import com.lamda.zhekou.master.event.DataCallBack;
import com.lamda.zhekou.master.session.WorkerSessionScheduler;
import com.lamda.zhekou.model.VPS;
import com.lamda.zhekou.vo.ResultVo;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

/**
 * Created by MJiao on 15/8/25.
 */
@Controller
public class CommandController {


    public static final Logger LOGGER = Logger.getLogger(CommandController.class);

    @Autowired
    private WorkerSessionScheduler workerSessionScheduler;

    @Autowired
    private ServerHostManager serverHostManager;

    @RequestMapping(value = "/vpsRestart")
    @ResponseBody
    public ResultVo vpsRestart(Long vpsId) {
        VPS vps = this.serverHostManager.getVpsByVpsId(vpsId);
        ResultVo resultVo = this.executeCommonCommand(vps.getComputerName(), vps.getVmName(), vps.getWorkerIp(), Configuration.Route.RESTART);

        return resultVo;
    }

    @RequestMapping(value = "/vpsStart")
    @ResponseBody
    public ResultVo vpsStart(Long vpsId) {
        VPS vps = this.serverHostManager.getVpsByVpsId(vpsId);
        ResultVo resultVo = this.executeCommonCommand(vps.getComputerName(), vps.getVmName(), vps.getWorkerIp(), Configuration.Route.START);

        return resultVo;
    }

    @RequestMapping(value = "/vpsPowerOff")
    @ResponseBody
    public ResultVo vpsPowerOff(Long vpsId) {

        VPS vps = this.serverHostManager.getVpsByVpsId(vpsId);

        ResultVo resultVo = this.executeCommonCommand(vps.getComputerName(), vps.getVmName(), vps.getWorkerIp(), Configuration.Route.POWER_OFF);

        return resultVo;
    }
    public ResultVo userVpsPowerOff(Long vpsId) {

        VPS vps = this.serverHostManager.getVpsByVpsId(vpsId);

        ResultVo resultVo = this.executeCommonCommand(vps.getComputerName(), vps.getVmName(), vps.getWorkerIp(), Configuration.Route.POWER_OFF);

        return resultVo;
    }
    @RequestMapping(value = "/createSnapshot")
    @ResponseBody
    public ResultVo createSnapshot(Long vpsId) {

        VPS vps = this.serverHostManager.getVpsByVpsId(vpsId);

        ResultVo resultVo = this.executeCommonCommand(vps.getComputerName(), vps.getVmName(), vps.getWorkerIp(), Configuration.Route.CREATE_SNAPSHOT);
        if (resultVo.isSucc()) {
            resultVo.setMsg("备份成功");
        } else {
            resultVo.setMsg("备份失败,请重试");
        }
        return resultVo;
    }
    @RequestMapping(value = "/restoreSnapshot")
    @ResponseBody
    public ResultVo restoreSnapshot(Long vpsId) {

        VPS vps = this.serverHostManager.getVpsByVpsId(vpsId);

        ResultVo resultVo = this.executeCommonCommand(vps.getComputerName(), vps.getVmName(), vps.getWorkerIp(), Configuration.Route.RESTORE_SNAPSHOT);

        return resultVo;
    }
    @RequestMapping(value = "/initVpsSnapshot")
    @ResponseBody
    public ResultVo initVpsSnapshot(Long vpsId) {

        VPS vps = this.serverHostManager.getVpsByVpsId(vpsId);

        ResultVo resultVo = this.executeCommonCommand(vps.getComputerName(), vps.getVmName(), vps.getWorkerIp(), Configuration.Route.INIT_VPS_SNAPSHOT);

        return resultVo;
    }
    private ResultVo executeCommonCommand(String computerName, String vmName, String workerIp, String route) {

        JSONObject jsonObject = new JSONObject();
        jsonObject.put("vmName", vmName);
        jsonObject.put("computerName", computerName);
        jsonObject.put("workerIp", workerIp);

        ResultVo resultVo = null;


        int tryCount = 5;
        while (tryCount > 0) {
            tryCount--;
            resultVo = retryExecuteCmd(route, jsonObject);
            if (resultVo.isSucc()) {
                break;
            }
        }
        return resultVo;
    }

    private ResultVo retryExecuteCmd(String route, JSONObject jsonObject) {

        ResultVo resultVo = new ResultVo();
        // 开始的倒数锁
        final CountDownLatch countDownLatch = new CountDownLatch(1);
        workerSessionScheduler.push(route, jsonObject, new DataCallBack() {
            @Override
            public void responseData(JSONObject message) {
                LOGGER.info("命令执行结果:" + message);

                boolean succ = message.containsKey("succ") && message.getBoolean("succ");
                resultVo.setSucc(succ);
                resultVo.setMsg(message.getString("msg"));

                // 每个选手到达终点时，end就减一
                countDownLatch.countDown();
            }
        });
        // 等待end变为0，即所有选手到达终点
        try {
            countDownLatch.await(60*3, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            e.printStackTrace();
            resultVo.setSucc(false);
            resultVo.setMsg("未知异常");
        }
        return resultVo;
    }
}
